home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
printing
/
rlpr-1.000
/
rlpr-1
/
rlpr-1.13
/
rlpr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-30
|
11KB
|
295 lines
/* filename: rlpr.c
* project: rlpr
* author: meem -- meem@sherilyn.wustl.edu
* version: $Id: rlpr.c,v 1.13 1996/07/01 01:06:02 meem Exp $
* contents: functions pertinent to the main flow of the program
*
* Time-stamp: <1996/06/30 20:36 -- meem@sherilyn>
*/
/* copyright (c) 1996 meem, meem@gnu.ai.mit.edu
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <stdio.h>
#include <string.h> /* for strcpy() strcat(), etc */
#include <stdlib.h> /* for malloc(), getenv(), etc */
#include <unistd.h> /* for unlink(), getopt(), etc */
#include <fcntl.h> /* for O_RDWR, etc */
#include <getopt.h> /* won't compile w/o this - why?! */
#include <pwd.h> /* for accessing the password file */
#include "rlpr.h"
#include "rlpr-net.h" /* network rlpr commands are here */
#include "rlpr-dbfile.h" /* accessing the rlpr database file */
#include "rlpr-common.h" /* common to all rlpr c source files */
/* TO DO: unhardcode port numbers
* supress printing of burst page broken? (all of burst page processing!?)
*/
int main(int argc, char *argv[]) {
int cfd; /* control file descriptor */
int tempargc;
char *cfname; /* control file name */
char *dfname; /* data file name */
char *cffullname; /* full pathname to control file */
int i; /* scrap variable */
int nf; /* number of files spooled */
name = *argv; /* program name */
get_local_hostname();
parse_args(argc, argv);
++argv; --argc; /* skip name */
while (argc && **argv == '-') { /* skip command-line options */
argv++;
argc--;
}
/* create name templates for temp files */
cfname = malloc(strlen(local_hostname) + strlen("cfAxxx") + 1);
dfname = malloc(strlen(local_hostname) + strlen("dfAxxx") + 1);
sprintf(cfname, "cfA%03d%s", getpid() % 1000, local_hostname);
cffullname = malloc(strlen(cfname) + strlen(TMPDIR) + 1);
sprintf(cffullname, "%s%s", TMPDIR, cfname);
strcpy(dfname, cfname);
*dfname = 'd';
if (!opts_.wflag) {
open_connection(); /* global sock is now open */
recv_job_req(); /* inform lpd we have job(s) */
}
nf = argc ? argc : 1; /* number of files */
/* open the cf once. we're going to keep reusing the same one
* on the client side because we only need one cf at a time
*/
if ((cfd = open(cffullname, O_RDWR|O_TRUNC|O_CREAT)) < 0)
rlpr_fatal("open on control file: %s", ERRNO);
unlink(cffullname);
do {
if (opts_.wflag) {
open_connection();
recv_job_req();
}
lseek(cfd, 0, SEEK_SET); /* reposition at start of file */
cf_header(cfd, argc ? *argv : NULL);
for (i = 0; i < opts_.copies; i++) /* print multiple copies */
cf_add(opts_.filetype, dfname, cfd);
cf_add('U', dfname, cfd);
send_cf(cfd, cfname);
send_df(argc ? *argv : NULL, dfname);
if (opts_.rflag && argc) /* make sure we're not stdin */
if ((unlink(*argv)) < 0)
rlpr_warn("%s: %s", *argv, ERRNO);
argv++;
dfname[2]++; /* inc. letter (dfA --> dfB), etc */
cfname[2]++;
if (opts_.wflag) close_connection();
} while (--argc > 0);
if (!opts_.wflag) close_connection(); /* global sock is now closed */
if (!opts_.qflag) {
printf("%i file%s spooled to %s:%s", nf, (nf > 1) ? "s" : "",
opts_.printhost, opts_.printer);
if (*opts_.proxyhost) printf(" (proxy: %s)", opts_.proxyhost);
putchar('\n');
}
exit(0);
}
void init_options(void) {
char *tmp;
opts_.fflag = 0; /* don't auto-form feed by default */
opts_.bflag = 1; /* burst page on by default */
opts_.qflag = 0; /* quiet off by default */
opts_.mflag = 0; /* don't mail after printing */
opts_.rflag = 0; /* don't remove after printing */
opts_.wflag = 0; /* windows braindead mode (off) */
opts_.filetype = ' '; /* no file type yet known */
opts_.icols = 0; /* number of columns to indent output */
opts_.copies = 1; /* number of copies to make */
opts_.width = 132; /* according to rfc 1179 */
opts_.job[0] = opts_.class[0] = opts_.title[0] = opts_.user[0] = '\0';
/* find out what host we are */
if ((gethostname(opts_.currhost, MAXHOSTNAMELEN)) < 0)
rlpr_fatal("unable to resolve current hostname!");
if ((tmp = getenv(PROXY))) /* PROXY is #defined in rlpr-common.h */
strncpy(opts_.proxyhost, tmp, MAXHOSTNAMELEN);
else opts_.proxyhost[0] = '\0';
if ((tmp = getenv(PRINTHOST))) /* PRINTHOST is #defined in rlpr-common.h */
strncpy(opts_.printhost, tmp, MAXHOSTNAMELEN);
else opts_.printhost[0] = '\0';
/* first consult PRINTER, if it's NULL then LPDEST */
if (!(tmp = getenv("PRINTER"))) tmp = getenv("LPDEST");
if (tmp) strncpy(opts_.printer, tmp, MAX_QUEUE_LEN);
else opts_.printer[0] = '\0';
}
void tidy_options(void) {
struct passwd *pw;
if (opts_.filetype == ' ') /* default to regular */
opts_.filetype = 'f';
if (!*opts_.user) /* apparently harmless (!!!!) */
if ((pw = getpwuid(getuid())))
strncpy(opts_.user, pw->pw_name, MAX_USER_LEN);
else rlpr_fatal("who are you?");
if (!*opts_.printhost && !*opts_.printer)
rlpr_fatal("no host or queue specified -- consult man page");
else if (!*opts_.printhost)
strncpy(opts_.printhost, gethostfromq(opts_.printer), MAX_QUEUE_LEN);
else if (!*opts_.printer)
strncpy(opts_.printer, getqfromhost(opts_.printhost), MAXHOSTNAMELEN);
}
/* add an entry to the control file */
void cf_add(char op, char *str, int cfd) { /* always terminated with LF */
char buf[MAX_STR_LEN];
sprintf(buf, "%c%s", op, str);
strcat(buf, "\n");
if (write(cfd, buf, strlen(buf)) < 0)
rlpr_fatal("write on control file: %s", ERRNO);
}
/* uses options struct to put standard header on control file */
void cf_header(int cfd, char *filename) {
char tmp[MAX_STR_LEN]; /* annoying */
if (!filename) filename = "stdin";
cf_add('H', opts_.currhost, cfd);
cf_add('P', opts_.user, cfd);
sprintf(tmp, "%i", opts_.width);
cf_add('W', tmp, cfd); /* width for f, l and p files */
if (opts_.icols) {
sprintf(tmp, "%i", opts_.icols);
cf_add('I', tmp, cfd);
}
if (opts_.mflag) /* mail user if appropriate */
cf_add('M', opts_.user, cfd);
if (*opts_.title) /* title for pr(1). rfc states */
cf_add('T', opts_.title, cfd); /* it is ignored for other commands */
if (opts_.bflag) { /* print burst page */
cf_add('L', opts_.user, cfd); /* USER NAME CAN BE OMITTED!? */
cf_add('C', *opts_.class ? opts_.class : local_hostname, cfd);
if (*opts_.job) /* not sure if rfc means name omitted */
cf_add('J', opts_.job, cfd); /* or command omitted */
}
if (opts_.filetype == 'p' && !*opts_.title) /* not sure if this is right either */
cf_add('N', filename, cfd);
}
void parse_args(int argc, char *argv[]) {
int c;
opterr = 0; /* don't let getopt write to stderr */
init_options(); /* initialize the options */
while ((c = getopt(argc, argv,
"1234cdfglnopqtv#:hi:mrsw:C:FH:J:P:Q:T:U:VWX:")) != EOF)
switch(c) {
/* user is on best behavior here. that is, we assume the user
actually has a file of the proper type, without checking that it
is of that type. set the filetype characteristic accordingly */
case '1': /* troff type R */
case '2': /* troff type I */
case '3': /* troff type B */
case '4': /* troff type S */
case 'c': /* cifplot */
case 'd': /* TeX/DVI */
case 'f': /* fortran */
case 'g': /* graph */
case 'l': /* leave control characters */
case 'n': /* ditroff */
case 'o': /* postscript (not in rlpr) */
case 'p': /* pr */
case 't': /* troff */
case 'v': /* raster input */
if (opts_.filetype != ' ')
rlpr_fatal("cannot send as two different assumed file types!");
opts_.filetype = (c == 'f') ? 'r' : c;
break;
case '#': /* number of copies to make */
opts_.copies = atoi(optarg); break;
case 'h': /* suppress printing of burst page */
opts_.bflag = 0; break;
case 'i': /* indentation */
opts_.icols = atoi(optarg); break;
case 'm': /* send mail after printing */
opts_.mflag = 1; break;
case 'q': /* be quiet! */
opts_.qflag = 1; break;
case 'r': /* remove file after printing */
opts_.rflag = 1; break;
case 's': /* for compatibility with BSD lpr */
rlpr_warn("symbolic link option not applicable (ignored)");
break;
case 'w': /* width for pr */
opts_.width = atoi(optarg); break;
case 'C': /* class */
strncpy(opts_.class, optarg, MAX_CLASS_LEN); break;
case 'F': /* form feed after printing */
opts_.fflag = 1; break;
case 'H': /* for overriding PRINTHOST */
strncpy(opts_.printhost, optarg, MAX_HOST_LEN); break;
case 'J': /* job name on burst page */
strncpy(opts_.job, optarg, MAX_JOB_LEN); break;
case 'P': /* printer queue name */
case 'Q': /* i think this is a better name */
strncpy(opts_.printer, optarg ,MAX_QUEUE_LEN); break;
case 'T': /* title for pr (def: filename) */
strncpy(opts_.title, optarg, MAX_TITLE_LEN); break;
case 'U': /* user (weary about this field) */
strncpy(opts_.user, optarg, MAX_USER_LEN); break;
case 'V': /* print version info */
fprintf(stdout, "%s: version "VERSION" from "__DATE__" "__TIME__
" -- meem@gnu.ai.mit.edu\n", name);
exit(0);
case 'W':
opts_.wflag = 1; break;
case 'X': /* for overriding PROXY */
strncpy(opts_.proxyhost, optarg, MAXHOSTNAMELEN); break;
case '?':
switch (optopt) {
case 'i':
opts_.icols = 8; break;
case 'w':
opts_.width = 80; break;
default:
rlpr_warn("unknown command line option -%c", optopt);
break;
}
}
tidy_options();
}